-- To get an item id easiest, use wowhead and search for name and then use item query parameter value


SARFFIX2_CONJURE_WATER_FORMAT 		= "Conjure Water(Rank %s)"
SARFFIX2_CONJURE_FOOD_FORMAT 		= "Conjure Food(Rank %s)"
SARFFIX2_CONJURE_GEM_FORMAT 		= "Conjure Mana %s"
SARFFIX2_CONJURE_GEMS				= {
	[1] = "Agate";
	[2] = "Jade";
	[3] = "Citrine";
	[4] = "Ruby";
	[5] = "Emerald";
};


SARFFIX2_CONJURE_HEALTHSTONE_FORMAT = "Create Healthstone(Rank %s)"
SARFFIX2_CONJURE_SOULSTONE_FORMAT 	= "Create Soulstone(Rank %s)"
SARFFIX2_CONJURE_FIRESTONE_FORMAT 	= "Create Firestone(Rank %s)"
SARFFIX2_CONJURE_SPELLSTONE_FORMAT 	= "Create Spellstone(Rank %s)"

SARFFIX2_CONJURE_HEALTHSTONES		= {
	[1] = {
		itemId = {
			5512;
			19004;
			19005;
		};
	};
	[2] = {
		itemId = {
			5511;
			19006;
			19007;
		};
	};
	[3] = {
		itemId = {
			5509;
			19008;
			19009;
		};
	};
	[4] = {
		itemId = {
			5510;
			19010;
			19011;
		};
	};
	[5] = {
		itemId = {
			9421;
			19012;
			19013;
		};
	};
	[6] = {
		itemId = {
			22103;
			22104;
			22105;
		};
	};
};

SARFFIX2_CONJURE_SOULSTONES			= {
};

SARFFIX2_CONJURE_FIRESTONES			= {
};

SARFFIX2_CONJURE_SPELLSTONES		= {
};


SarfFix2_SmartBuff_Options = {
	addAllGems = false;
	timeBetweenChecks = 15;
};

SarfFix2_SmartBuff = {
	setup = {
		itemsAndMinimums = {
		};
		hookedFuncs = {};
	};
	options = SarfFix2_SmartBuff_Options;
};

function SarfFix2_SmartBuff:Hook()
	
	self.setup.hookedFuncs.SMARTBUFF_Check = SMARTBUFF_Check;
	SMARTBUFF_Check = function(mode, forced, p1, p2, p3, p4, p5) return SarfFix2_SmartBuff:SMARTBUFF_Check(mode, forced, p1, p2, p3, p4, p5); end
	
	--self.setup.oldInit = SMARTBUFF_SetBuffs;
	--SMARTBUFF_SetBuffs = SarfFix2_SmartBuff_SetBuffs;
end


function SarfFix2_SmartBuff:GetConjureGemSpell(rank)
	local gem = SARFFIX2_CONJURE_GEMS[rank];
	if ( gem ) then
		return string.format(SARFFIX2_CONJURE_GEM_FORMAT, gem);
	else
		return "No Such Gem";
	end
end

function SarfFix2_SmartBuff:Setup()
	local class;
	
	_, class = UnitClass("player");
	
	self.setup.class = class;
	self.setup.itemsAndMinimums = {};
	
	
	local funcName = class.."_Setup";
	if ( type(self[funcName]) == "function" ) then
		self[funcName](self);
		self:Hook();
	end
	
end

function SarfFix2_SmartBuff:MAGE_AddConjureSpell(conjureSpell, spellKey, minimumAmount, spellPattern)
	if ( not minimumAmount ) or ( minimumAmount <= 0 ) then
		minimumAmount = 1;
	end
	local arr = {};
	arr.minimumAmount = minimumAmount;
	for key, value in pairs(conjureSpell) do
		arr[key] = value;
	end
	arr.spell = self:MAGE_GetSpellDataName(arr, spellPattern);
	self.setup.itemsAndMinimums[spellKey] = arr;
end

function SarfFix2_SmartBuff:HasSpellReal(spellArg, spellRank)
	local rankIndex = string.find(spellName, "%(");
	local spellName = spellArg;
	local rankName = spellRank;
	if ( rankIndex ) then
		rankName = string.gsub(spellName, "%((%a+)%)");
		spellName = string.sub(spellName, 1, rankIndex-1);
	end
	
	
	local i = 1
	local spell, rank;
	while true do
		spell, rank = GetSpellName(i, BOOKTYPE_SPELL)
		if not spell then
			do break end
		end
		if ( spellName == spellName ) then
			if ( not rankName ) or ( rankName == rank ) then
				return true;
			end
		end
		i = i + 1
	end
	return false;
end
	
function SarfFix2_SmartBuff:HasSpell(spellArg)
-- TODO: use HasSpellReal once it has been tested.	
	return true;
end


function SarfFix2_SmartBuff:MAGE_GetSpellDataName(spellData, spellPattern)
	if ( not spellData.spell ) and ( spellData.spellRank ) then
		if ( not spellPattern ) then
			ChatFrame1:AddMessage("No spellpattern when needed. Entry data:");
			for k,v in pairs(spellData) do
				ChatFrame1:AddMessage(k.." => "..v);
			end
			return nil;
		else
			-- optimization:
			spellData.spell = string.format(spellPattern, spellData.spellRank);
			--return string.format(spellPattern, spellData.spellRank);
		end
	end
	return spellData.spell;
end

function SarfFix2_SmartBuff:MAGE_FixSpell(spellList, spellKey, minimumAmount, spellPattern, addAll)
	local spell = nil;
	local level = UnitLevel("player");
	local maxLevel = -1;
	for key, value in pairs(spellList) do
		if ( type(key) == "number" ) and ( level >= key ) and ( key > maxLevel ) then
			if ( self:HasSpell(self:MAGE_GetSpellDataName(value, spellPattern) ) ) then
				maxLevel = key;
				spell = value;
				if ( addAll ) then
					self:MAGE_AddConjureSpell(value, spellKey..key, minimumAmount, spellPattern);
				end
			end
		end
	end
	if ( spell ) then
		if ( not addAll ) then
			self:MAGE_AddConjureSpell(spell, spellKey, spell.minimumAmount, spellPattern);
		end
		return true;
	else
		return false;
	end
end

function SarfFix2_SmartBuff:MAGE_Setup()
	local waters = {
		[4] = {
			itemId = 5350;
			spellRank = 1;
		};
		[10] = {
			itemId = 2288;
			spellRank = 2;
		};
		[20] = {
			itemId = 2136;
			spellRank = 3;
		};
		[30] = {
			itemId = 3772;
			spellRank = 4;
		};
		[40] = {
			itemId = 8077;
			spellRank = 5;
		};
		[50] = {
			itemId = 8078;
			spellRank = 6;
		};
		[60] = {
			itemId = 8079;
			spellRank = 7;
		};
		[65] = {
			itemId = 30703;
			spellRank = 8;
		};
		[70] = {
			itemId = 22018;
			spellRank = 9;
		};
	};
	local foods = {
		[6] = {
			itemId = 5349;
			spellRank = 1;
		};
		[12] = {
			itemId = 1113;
			spellRank = 2;
		};
		[22] = {
			itemId = 1114;
			spellRank = 3;
		};
		[32] = {
			itemId = 1487;
			spellRank = 4;
		};
		[42] = {
			itemId = 8075;
			spellRank = 5;
		};
		[52] = {
			itemId = 8076;
			spellRank = 6;
		};
		[60] = {
			itemId = 22895;
			spellRank = 7;
		};
		[70] = {
			itemId = 22019;
			spellRank = 8;
		};
	};
	local getGem = function(rank) return SarfFix2_SmartBuff:GetConjureGemSpell(rank); end
	local gems = {
		[28] = {
			itemId = 5514;
			spell = getGem(1);
		};
		[38] = {
			itemId = 5513;
			spell = getGem(2);
		};
		[48] = {
			itemId = 8007;
			spell = getGem(3);
		};
		[58] = {
			itemId = 8008;
			spell = getGem(4);
		};
		[68] = {
			itemId = 22044;
			spell = getGem(5);
		};
	};
	
	self:MAGE_FixSpell(waters, "water", 4, SARFFIX2_CONJURE_WATER_FORMAT);
	self:MAGE_FixSpell(foods, "food", 4, SARFFIX2_CONJURE_FOOD_FORMAT);
	self:MAGE_FixSpell(gems, "gem", 1, nil, self.options.addAllGems);
	
end

function SarfFix2_SmartBuff:TimeSinceLastCheck()
	local curTime = GetTime();
	if ( self.setup.lastCheck ) and ( self.setup.lastCheck > 0 ) then
		return curTime - self.setup.lastCheck;
	else
		return -1;
	end
end

function SarfFix2_SmartBuff:ShouldCheck(timeBetween)
	if ( InCombatLockdown() ) then
		return false;
	end
	if ( not timeBetween ) then
		timeBetween = self.options.timeBetweenChecks;
	end
	local timeSince = self:TimeSinceLastCheck();
	return ( timeSince <= -1 ) or ( timeBetween >= timeSince );
end

function SarfFix2_SmartBuff:Checking()
	self.setup.lastCheck = GetTime();
end

function SarfFix2_SmartBuff:CheckIfNeeded()
	if ( self:ShouldCheck() ) then
		self:Checking();
		local func = self[self.setup.class.."_Check"];
		if ( func ) and ( type(func) == "function" ) then
			return func(self);
		end
	end
	return false;
end

function SarfFix2_SmartBuff:Check()
	local func = self[self.setup.class.."_Check"];
	if ( func ) and ( type(func) == "function" ) then
		return func(self);
	end
	return false;
end

function SarfFix2_SmartBuff:PerformCast(spell)
    SmartBuff_KeyButton:SetAttribute("type", "spell");
    SmartBuff_KeyButton:SetAttribute("spell", spell);
    SmartBuff_KeyButton:SetAttribute("item", nil);
    SmartBuff_KeyButton:SetAttribute("target-slot", nil); 
    SmartBuff_KeyButton:SetAttribute("action", nil);
end

function SarfFix2_SmartBuff:CheckAndCast()
	local func = self[self.setup.class.."_CheckAndCast"];
	if ( func ) and ( type(func) == "function" ) then
		return func(self);
	end
	return false;
end

function SarfFix2_SmartBuff:CastSpell(spell)
	SMARTBUFF_doCast("player", SMARTBUFF_GetSpellID(spell), spell, nil, SMARTBUFF_CONST_SELF);
end

function SarfFix2_SmartBuff:CheckForItemMinimumAndGetSpell(itemId, minimumAmount, spell)
	if ( not itemId ) or ( itemId == 0 ) then
		ChatFrame1:AddMessage("no item id");
		return false;
	end
	local items = self:GetItemCountInBags(itemId);
	if ( minimumAmount ) and ( items < minimumAmount ) then
		-- ChatFrame1:AddMessage("minimum amount less than amount of items");
		return spell;
	end
	if ( not minimumAmount ) then
		-- ChatFrame1:AddMessage("minimum amount nil");
	end
	if ( minimumAmount > items ) then
		-- ChatFrame1:AddMessage("minimum amount more than current # of items in bags");
	end
	return nil;
end

function SarfFix2_SmartBuff:SMARTBUFF_Check(mode, forced, p1, p2, p3, p4, p5)
	local spell = self:CheckAndCast();
	if ( spell ) then
		-- no idea, item/spell, spell name, inventory slot, unit, bufftype (from top of sb.buffs.lua
		return 0, SMARTBUFF_ACTION_SPELL, spell, -1, "player", SMARTBUFF_CONST_SELF;
	else
		return self.setup.hookedFuncs.SMARTBUFF_Check(mode, forced, p1, p2, p3, p4, p5);
	end
end

function SarfFix2_SmartBuff:MAGE_CheckAndCast()
	local spell = nil;
	for key, value in pairs(self.setup.itemsAndMinimums) do
		spell = self:CheckForItemMinimumAndGetSpell(value.itemId, value.minimumAmount, value.spell);
		if ( spell ) then
			return spell;
		end
	end
	return;
end

function SarfFix2_SmartBuff:GetItemCountInBags(itemId)
	local itemName, itemLink, _, _, _, _, _, _, _, itemTexture = GetItemInfo(itemId);
	local bag, slot;
	local texture, count, link;
	local partialLink = "item:"..itemId..":";
	local totalCount = 0;
	for bag = 0, 4 do
		for slot = 1, GetContainerNumSlots(bag) do
			texture, count = GetContainerItemInfo(bag, slot);
			if ( ( texture ) and ( texture == itemTexture ) and ( count ) ) then
				link = GetContainerItemLink(bag, slot);
				if ( strfind(link, partialLink) ) then
					totalCount = totalCount + count;
				end
			end
		end
	end
	return totalCount;
end


function SarfFix2_SmartBuff:MAGE_Check()
	local spell = nil;
	for key, value in pairs(self.setup.itemsAndMinimums) do
		spell = self:CheckForItemMinimumAndGetSpell(value.itemId, value.minimumAmount, value.spell);
		if ( spell ) then
			-- no idea, item/spell, spell name, inventory slot, unit, bufftype (from top of sb.buffs.lua
			return 0, SMARTBUFF_ACTION_SPELL, spell, -1, "player", SMARTBUFF_CONST_SELF;
			--return true;
		end
	end
	return;
end

local f = CreateFrame("Frame", "SarfFix2_SmartBuffFrame");

f:RegisterEvent("PLAYER_ENTERING_WORLD");
f:SetScript("OnEvent", function() SarfFix2_SmartBuff:Setup() end);

-- SarfFix2_SmartBuff:Setup();
